#ifndef __UTOOLS_COLLAB_SYNC_LIST_H__
#define __UTOOLS_COLLAB_SYNC_LIST_H__

#include "../utools_cfg.h"

#if UTOOLS_COLLAB_SYNC_LIST_ENABLE

#include <list>
#include <functional>
#include "utcondition_variable.h"
#include "utmutex.h"

#if __cplusplus >= 201703L
#include <optional>
#endif

namespace utools::collab
{
    /// @brief 同步列表
    /// @tparam _SYNC_DATA_TYPE 对列中的数据类型
    /// @tparam DATA_COUNT 最大队列大小，如果为0，则不限制队列大小
    template <typename _SYNC_DATA_TYPE, size_t DATA_COUNT = 20>
    class SyncList
    {
    public:
        using size_type = typename std::list<_SYNC_DATA_TYPE>::size_type;
        using value_type = typename std::list<_SYNC_DATA_TYPE>::value_type;
        using reference = typename std::list<_SYNC_DATA_TYPE>::reference;
        using const_reference = typename std::list<_SYNC_DATA_TYPE>::const_reference;

        SyncList() = default;
        virtual ~SyncList() = default;

        /// @brief 向对列中增加一个数据
        /// @param data 要增加的数据
        template <typename T,
                  typename = std::enable_if_t<std::is_same_v<std::decay_t<T>, value_type>>>
        void push(T &&data)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            if constexpr (DATA_COUNT > 0)
            {
                while (__list.size() >= DATA_COUNT)
                {
                    __list.pop_front();
                }
            }
            __list.push_back(std::forward<T>(data));
            __cv.notify_one();
        }

        /// @brief 向对列中增加一个数据，会直接调用构造函数
        /// @param args 要增加的数据的变量
        template <typename... Args>
        void emplace(Args &&...args)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            if constexpr (DATA_COUNT > 0)
            {
                while (__list.size() >= DATA_COUNT)
                {
                    __list.pop_front();
                }
            }
            __list.emplace_back(std::forward<Args>(args)...);
            __cv.notify_one();
        }

#if __cplusplus >= 201703L
        /// @brief 等待数据并弹出，会返回数据
        /// @return 头部数据或空std::nullopt
        /// @note 如果接收到__released信号，会直接返回std::nullopt
        std::optional<value_type> pop_wait_safety()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            while (__list.empty() && !__released)
            {
                __cv.wait(lock);
            }
            if (__released && __list.empty())
            {
                return std::nullopt;
            }
            auto data{std::move(__list.front())};
            __list.pop_front();
            return data;
        }
#endif

        /// @brief 等待数据弹出，会返回数据
        /// @return 头部数据
        /// @warning 如果接收到__released信号，会优化判断是否可以返回nullptr数据
        /// @warning 如果不行会直接返回数据类型对应的默认构造值，这可能是不安全的
        value_type pop_wait()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            while (__list.empty() && !__released)
            {
                __cv.wait(lock);
            }
            if (__released)
            {
                if constexpr (std::is_pointer<value_type>::value ||
                              std::is_convertible<value_type, std::nullptr_t>::value)
                {
                    return nullptr;
                }
                else
                {
                    return value_type{};
                }
            }
            auto data{std::move(__list.front())};
            __list.pop_front();
            return data;
        }

        /// @brief 等待数据弹出，会返回数据
        /// @param data 返回的数据
        /// @warning 如果接收到__released信号，会优化判断是否可以返回nullptr数据
        /// @warning 如果不行会直接返回数据类型对应的默认构造值，这可能是不安全的
        void pop_wait(value_type &data)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            while (__list.empty() && !__released)
            {
                __cv.wait(lock);
            }
            if (__released)
            {
                if constexpr (std::is_pointer<value_type>::value ||
                              std::is_convertible<value_type, std::nullptr_t>::value)
                {
                    data = nullptr;
                }
                else
                {
                    data = value_type{};
                }
            }
            else
            {
                data = std::move(__list.front());
                __list.pop_front();
            }
        }

        /// @brief 等待数据非空时
        /// @return true: 队列非空，false: 队列已释放
        bool wait_not_empty()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            while (__list.empty() && !__released)
            {
                __cv.wait(lock);
            }
            return !__released;
        }

        /// @brief 只弹出数据，不会返回任何数据
        void pop()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            if (!__list.empty())
            {
                __list.pop_front();
            }
        }

        void push_back(const value_type &item)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.push_back(item);
            __cv.notify_one();
        }

        void push_front(const value_type &item)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.push_front(item);
            __cv.notify_one();
        }

        /// @brief 批量操作：一次性添加多个元素到末尾（拷贝版本）
        /// @tparam Iterator 迭代器类型
        /// @param first 开始迭代器
        /// @param last 结束迭代器
        /// @note 性能优化：减少锁获取次数
        template <typename Iterator>
        void push_back_batch(Iterator first, Iterator last)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            size_t count = 0;
            for (auto it = first; it != last; ++it)
            {
                __list.push_back(*it);
                ++count;
            }
            if (count > 0)
            {
                __cv.notify_all(); // 批量通知
            }
        }

        /// @brief 批量操作：一次性移动多个元素到末尾（移动版本）
        /// @tparam Container 容器类型
        /// @param container 要移动的容器
        /// @note 零拷贝优化：使用移动语义避免复制开销
        template <typename Container>
        void push_back_batch_move(Container&& container)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            size_t count = 0;
            for (auto& item : container)
            {
                __list.push_back(std::move(item));
                ++count;
            }
            if (count > 0)
            {
                __cv.notify_all(); // 批量通知
            }
        }

        /// @brief 批量操作：使用函数对象批量构建元素（零拷贝优化）
        /// @tparam Generator 生成器函数类型
        /// @param count 要生成的元素数量
        /// @param generator 生成器函数，接受索引参数，返回要构建的元素
        /// @note 终极优化：直接在目标容器中构建，避免任何中间容器
        template <typename Generator>
        void emplace_back_batch(size_t count, Generator generator)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            for (size_t i = 0; i < count; ++i)
            {
                __list.emplace_back(generator(i));
            }
            if (count > 0)
            {
                __cv.notify_all(); // 批量通知
            }
        }

        bool pop_front(value_type &item)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            if (__list.empty())
            {
                return false;
            }
            item = std::move(__list.front());
            __list.pop_front();
            return true;
        }

        bool pop_back(value_type &item)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            if (__list.empty())
            {
                return false;
            }
            item = std::move(__list.back());
            __list.pop_back();
            return true;
        }

        bool wait_and_pop_front(value_type &item)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            while (__list.empty() && !__released)
            {
                __cv.wait(lock);
            }
            if (__released && __list.empty())
            {
                return false;
            }
            item = std::move(__list.front());
            __list.pop_front();
            return true;
        }

        size_t size() const
        {
            ::utools::collab::UniqueLock lock(__mutex);
            return __list.size();
        }

        bool empty() const
        {
            ::utools::collab::UniqueLock lock(__mutex);
            return __list.empty();
        }

        /// @brief 性能优化：无锁检查是否为空（适用于某些场景）
        /// @warning 仅在确保线程安全的情况下使用
        /// @note 用于高频检查场景，避免锁开销
        bool empty_unsafe() const noexcept
        {
            return __list.empty();
        }

        /// @brief 性能优化：无锁获取大小（适用于某些场景）
        /// @warning 仅在确保线程安全的情况下使用
        /// @note 用于高频检查场景，避免锁开销
        size_t size_unsafe() const noexcept
        {
            return __list.size();
        }

        void clear()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.clear();
        }

        void remove(const value_type &value)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.remove(value);
        }

        template <class Predicate>
        void remove_if(Predicate pred)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.remove_if(pred);
        }

        /// @brief 对列表中的每个元素执行指定操作（线程安全）
        /// @tparam Function 函数对象类型
        /// @param func 要执行的函数对象
        /// @note 新增方法：支持 pubsub.h 中的 for_each 操作
        template <class Function>
        void for_each(Function func)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            for (auto &item : __list)
            {
                func(item);
            }
        }

        /// @brief 移除列表中相邻的重复元素，仅保留每个唯一元素的第一个副本。
        /// 该函数会对列表进行遍历，比较相邻元素，若相邻元素相等，则移除重复的元素。
        /// 操作过程中会加锁以保证线程安全。
        void unique()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.unique();
        }

        void sort()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.sort();
        }

        template <class Compare>
        void sort(Compare comp)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.sort(comp);
        }

        void reverse()
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.reverse();
        }

        void splice(std::list<_SYNC_DATA_TYPE> &other)
        {
            ::utools::collab::UniqueLock lock(__mutex);
            __list.splice(__list.end(), other);
        }

        /// @brief 发送通知释放当前的pop()操作
        /// @warning 如不了解工作过程，请不要手动调用该函数
        void notify_one()
        {
            __cv.notify_one();
        }

        /// @brief 发送通知释放当前的pop()操作
        /// @warning 如不了解工作过程，请不要手动调用该函数
        void notify_all()
        {
            __cv.notify_all();
        }

        void release()
        {
            __released = true;
            notify_all();
        }

        /// @brief 重新初始化对列
        void reset()
        {
            __released = true;
            notify_all();
            ::utools::collab::UniqueLock lock(__mutex);
            __list = std::list<_SYNC_DATA_TYPE>();
            __released = false;
        }

        /// @brief 加锁
        void lock()
        {
            __mutex.lock();
        }

        /// @brief 解锁
        void unlock()
        {
            __mutex.unlock();
        }

        /// @brief 获取列表（不安全，已弃用）
        /// @deprecated 此方法不安全，请使用 for_each 或其他线程安全方法
        /// @warning 返回内部容器引用，可能导致线程安全问题
        [[deprecated("Use for_each() or other thread-safe methods instead")]]
        std::list<_SYNC_DATA_TYPE> &data()
        {
            return __list;
        }

        /// @brief 安全的数据访问：获取列表副本
        /// @return 列表的副本
        /// @note 线程安全的替代方案
        std::list<_SYNC_DATA_TYPE> get_copy() const
        {
            ::utools::collab::UniqueLock lock(__mutex);
            return __list; // 返回副本
        }

    private:
        ::utools::collab::Mutex __mutex;
        ::utools::collab::ConditionVariable __cv;
        std::list<_SYNC_DATA_TYPE> __list;
        bool __released{false};
    };

} // namespace utools

#endif // UTOOLS_COLLAB_SYNC_LIST_ENABLE
#endif // __UTOOLS_COLLAB_SYNC_LIST_H__